package view;

import interfaces.ViewPanel;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Vector;

import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import com.toedter.calendar.JDateChooser;
import utils.CommandGenerator;
import utils.KeyboardManager;
import control.CategoryManager;
import control.ExpenseManager;
import control.MemberManager;
import control.PaymentMethodManager;
import control.Search;
import control.Shell;
import control.ValidateInput;
import control.ViewPanelManager;
import domain.Category;
import domain.Expense;
import domain.FamilyMember;
import domain.PaymentMethod;
import enums.Frequency;

//@author A0098891H
public class ExpenseManagerPanel extends BackgroundPanel implements ViewPanel {

	/**
	 * 
	 */

	//public 	DefaultListModel<String> lm_expenseCategory;
	public 	DefaultComboBoxModel<Category> cbm_expenseCategory;
	public 	DefaultComboBoxModel<PaymentMethod> cbm_expensePayMethod;
	public 	DefaultComboBoxModel<FamilyMember> cbm_expenseMember;
	
	private JDateChooser calendarDate;
	private JLabel lbl_expenseName;
	private JTextField txt_expenseName;
	private JLabel lbl_expenseAmount;
	private JTextField txt_expenseAmount;
	private JComboBox<Category> cb_expenseCategory;
	private JLabel lbl_expenseByMember;
	private JComboBox<FamilyMember> cb_expenseByMem;
	private JLabel lbl_expenseCategory;
	private JComboBox<PaymentMethod> cb_expensePaymentMethod;
	private JLabel lbl_expensePaymentMode;
	private JLabel lbl_expensePaidTo;
	private JTextField txt_expensePaidTo;
	private JLabel lbl_expenseDescr;
	private JTextField txt_expenseDescr;
	private JLabel lbl_expenseDate;
	private JLabel lbl_expenseFrequency;
	private JComboBox<Frequency> cb_expenseFrequency;
	private JTable expenseTable;
	private Vector<Vector> expenseRowData;
	
	private JScrollPane scrollPane_xpnList;
	//private boolean isPeriodExpense;
	
	private JButton btn_addExpense;
	private JButton btn_deleteExpense;
	private JButton btn_editExpense;
	private JButton btnStopUpdate;
	private JButton btn_endPeriod;	
	private JButton btn_cancelEdit;
	private JButton btn_saveEdit;
	
	private ExpenseManager _xpnManager;
	private Shell _shell;
	private MemberManager _memManager;
	private CategoryManager _catManager;
	private PaymentMethodManager _payManager;
	private SidePane _sidePane;
	private Search _search;
	private ViewPanelManager _tabPanelMgr;
	private JButton btnAddCat;
	private JButton btbAddPayMethod;
	private JButton btnAddMem;


	public ExpenseManagerPanel(final ExpenseManager xpnManager, final Shell shell, 
			final MemberManager memManager, final CategoryManager catManager, 
			final PaymentMethodManager payManager, SidePane sidePane, ViewPanelManager tabPanelMgr)
	{
		super();
		this.setLayout(null);
		_xpnManager = xpnManager;
		_shell = shell;
		_memManager = memManager;
		_catManager = catManager;
		_payManager = payManager;
		_sidePane = sidePane;
		_tabPanelMgr = tabPanelMgr;
		
		lbl_expenseName = new JLabel("Name");
		lbl_expenseName.setBounds(27, 14, 122, 17);
		this.add(lbl_expenseName);

		txt_expenseName = new JTextField();
		txt_expenseName.setColumns(10);
		txt_expenseName.setBounds(27, 38, 131, 23);
		this.add(txt_expenseName);
		
		lbl_expenseAmount = new JLabel("Amount");
		lbl_expenseAmount.setBounds(27, 65, 122, 17);
		this.add(lbl_expenseAmount);
		
		txt_expenseAmount = new JTextField();
		txt_expenseAmount.setColumns(10);
		txt_expenseAmount.setBounds(27, 86, 131, 23);
		this.add(txt_expenseAmount);
		
		lbl_expenseCategory = new JLabel("Category");
		lbl_expenseCategory.setBounds(27, 115, 112, 17);
		this.add(lbl_expenseCategory);
		
		cb_expenseCategory = new JComboBox<Category>(); 
		cb_expenseCategory.setBounds(27, 139, 131, 23);
		this.add(cb_expenseCategory);

		lbl_expenseByMember = new JLabel("By Member");
		lbl_expenseByMember.setBounds(27, 227, 122, 17);
		this.add(lbl_expenseByMember);
		
		cb_expenseByMem = new JComboBox<FamilyMember>();//add member
		cb_expenseByMem.setBounds(27, 253, 131, 23);
		this.add(cb_expenseByMem);
		
		cb_expensePaymentMethod = new JComboBox<PaymentMethod>();
		cb_expensePaymentMethod.setBounds(27, 196, 131, 23);
		this.add(cb_expensePaymentMethod);
		
		lbl_expensePaymentMode = new JLabel("Payment Method");
		lbl_expensePaymentMode.setBounds(27, 175, 122, 17);
		this.add(lbl_expensePaymentMode);

		lbl_expensePaidTo = new JLabel("Place/Paid to");
		lbl_expensePaidTo.setBounds(27, 283, 122, 17);
		this.add(lbl_expensePaidTo);
		
		txt_expensePaidTo = new JTextField();
		txt_expensePaidTo.setColumns(10);
		txt_expensePaidTo.setBounds(27, 303, 131, 23);
		this.add(txt_expensePaidTo);

		lbl_expenseDescr = new JLabel("Description");
		lbl_expenseDescr.setBounds(170, 16, 83, 18);
		this.add(lbl_expenseDescr);
		
		txt_expenseDescr = new JTextField();
		txt_expenseDescr.setColumns(10);
		txt_expenseDescr.setBounds(248, 14, 402, 21);
		this.add(txt_expenseDescr);
		
		lbl_expenseDate = new JLabel("Date");
		lbl_expenseDate.setBounds(661, 14, 38, 17);
		this.add(lbl_expenseDate);
		
		//txt_expenseDate = new JTextField();
		//txt_expenseDate.setColumns(10);
		//txt_expenseDate.setBounds(557, 10, 122, 23);
		//this.add(txt_expenseDate);
		calendarDate = new JDateChooser();
		calendarDate.setBounds(698, 11, 122, 23);
		calendarDate.setPreferredSize(new Dimension(90,20));
		calendarDate.setDateFormatString("dd/MM/yyyy");
		this.add(calendarDate);

		lbl_expenseFrequency = new JLabel("Frequency");
		lbl_expenseFrequency.setBounds(27, 334, 112, 17);
		this.add(lbl_expenseFrequency);
		
		cb_expenseFrequency = new JComboBox<Frequency>();
		cb_expenseFrequency.addItem(Frequency.NO);
		cb_expenseFrequency.addItem(Frequency.DAILY);
		cb_expenseFrequency.addItem(Frequency.WEEKLY);
		cb_expenseFrequency.addItem(Frequency.MONTHLY);
		cb_expenseFrequency.addItem(Frequency.YEARLY);
		cb_expenseFrequency.setBounds(27, 358, 131, 23);
		this.add(cb_expenseFrequency);
		
		/*lbl_expenseFrequency = new JLabel("End Period Expense?");
		lbl_expenseFrequency.setBounds(27, 382, 112, 17);
		this.add(lbl_expenseFrequency);
		
		btn_endPeriod = new JButton("Yes");
		btn_endPeriod.setBounds(27, 406, 122, 23);
		this.add(btn_endPeriod);
		btn_endPeriod.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				
			}
		});*/
		
		scrollPane_xpnList = new JScrollPane();
		scrollPane_xpnList.setBounds(170, 47, 650, 400);
		this.add(scrollPane_xpnList);
		
		
		_search = new Search(_xpnManager,catManager);
		UneditableTable vectorTable = new UneditableTable(null, Search.getToExpenseVectorColName());
		expenseTable = new JTable(vectorTable);
		expenseTable.setFont(new Font("Tahoma", Font.BOLD, 11));
		scrollPane_xpnList.setViewportView(expenseTable);
		
		
		btn_addExpense = new JButton("Add Expense");
		btn_addExpense.setBounds(175, 470, 122, 23);
		this.add(btn_addExpense);
		btn_addExpense.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				
				if(!validateInput())
					return;
				
				String cmd = CommandGenerator.getAddExpenseCmd(
						txt_expenseName.getText(), 
						Double.parseDouble(txt_expenseAmount.getText()), 
						((Category)cb_expenseCategory.getSelectedItem()).get_id(), 
						((PaymentMethod)cb_expensePaymentMethod.getSelectedItem()).get_id(), 
						((FamilyMember)cb_expenseByMem.getSelectedItem()).get_id(), 
						txt_expensePaidTo.getText(), 
						cb_expenseFrequency.getSelectedItem().toString(),
						((JTextField)calendarDate.getDateEditor().getUiComponent()).getText(), 
						txt_expenseDescr.getText());
				_shell.readCmd(cmd);
				updateTable();					
				setDefault();
				
			}
		});

		btn_deleteExpense = new JButton("Delete Expense");
		btn_deleteExpense.setBounds(687, 470, 122, 23);
		this.add(btn_deleteExpense);
		btn_deleteExpense.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				int selectedRow = expenseTable.getSelectedRow();
				if(selectedRow>=0)
				{	
					int expenseId = _search.getExpenseIdList().get(selectedRow);
					//System.out.println("delete id: "+ expenseId);
					String cmd = CommandGenerator.getDeleteExpenseCmd(expenseId);		
					_shell.readCmd(cmd);
					updateTable();
					
				}
				else
				{
					print("Please select an existing expense to delete.\n");
				}
				
			}
			
		});

		btn_editExpense = new JButton("Edit Expense");
		btn_editExpense.setBounds(427, 470, 122, 23);
		this.add(btn_editExpense);
		
		btn_saveEdit = new JButton();
		btn_saveEdit.setIcon(new ImageIcon(ExpenseManagerPanel.class.getResource("/images/save.png")));
		btn_saveEdit.setBounds(374, 458, 48, 48);
		btn_saveEdit.setVisible(false);
		btn_saveEdit.setBorderPainted(false);
		btn_saveEdit.setContentAreaFilled(false);
		btn_saveEdit.setFocusable(false);
		add(btn_saveEdit); 
		
		btn_cancelEdit = new JButton();
		btn_cancelEdit.setIcon(new ImageIcon(ExpenseManagerPanel.class.getResource("/images/cancel.png")));
		btn_cancelEdit.setBounds(553, 458, 48, 48);
		btn_cancelEdit.setVisible(false);
		btn_cancelEdit.setContentAreaFilled(false);
		btn_cancelEdit.setBorderPainted(false);
		btn_cancelEdit.setFocusable(false);
		add(btn_cancelEdit);
		
		btnStopUpdate = new JButton("Stop Update");
		btnStopUpdate.setVisible(false);
		btnStopUpdate.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				btnStopUpdate.setVisible(false);
				/*cb_expenseFrequency.addItem(Frequency.STOPPED);
				cb_expenseFrequency.setSelectedItem(Frequency.STOPPED);*/
				int selectedRow = expenseTable.getSelectedRow();
				int editId = _search.getExpenseIdList().get(selectedRow);
				Expense xpn = xpnManager.get(editId);
				//xpn.set_amount(xpn.get_totalAmount());
				xpn.set_frequency(Frequency.STOPPED);
				updateTable();
				setDefault();
			}
		});
		btnStopUpdate.setBounds(27, 405, 131, 23);
		add(btnStopUpdate);
		
		btnAddCat = new JButton("");
		btnAddCat.setIcon(new ImageIcon(ExpenseManagerPanel.class.getResource("/images/cat_add.png")));
		btnAddCat.setBounds(3, 138, 24, 24);
		btnAddCat.setBorderPainted(false);
		btnAddCat.setContentAreaFilled(false);
		btnAddCat.setFocusable(false);
		btnAddCat.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				KeyboardManager.genKeyEvent(KeyEvent.KEY_PRESSED, KeyEvent.CTRL_DOWN_MASK, KeyEvent.VK_C);
			}
		});
		add(btnAddCat);
		
		btbAddPayMethod = new JButton("");
		btbAddPayMethod.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				KeyboardManager.genKeyEvent(KeyEvent.KEY_PRESSED, KeyEvent.CTRL_DOWN_MASK, KeyEvent.VK_P);
			}
		});
		btbAddPayMethod.setBorderPainted(false);
		btbAddPayMethod.setContentAreaFilled(false);
		btbAddPayMethod.setFocusable(false);
		btbAddPayMethod.setIcon(new ImageIcon(ExpenseManagerPanel.class.getResource("/images/add.png")));
		btbAddPayMethod.setBounds(3, 195, 24, 24);
		add(btbAddPayMethod);
		
		btnAddMem = new JButton();
		btnAddMem.setBorderPainted(false);
		btnAddMem.setContentAreaFilled(false);
		btnAddMem.setFocusable(false);
		btnAddMem.setIcon(new ImageIcon(ExpenseManagerPanel.class.getResource("/images/user_add.png")));
		btnAddMem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				KeyboardManager.genKeyEvent(KeyEvent.KEY_PRESSED, KeyEvent.CTRL_DOWN_MASK, KeyEvent.VK_M);
			}
		});
		btnAddMem.setBounds(3, 252, 24, 24);
		add(btnAddMem);
	
		btn_editExpense.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				int selectedRow = expenseTable.getSelectedRow();
				if(selectedRow>=0)
				{
					int editId = _search.getExpenseIdList().get(selectedRow);
					Expense xpn = xpnManager.get(editId);
					//System.out.println("Edit id: "+ editId);
					txt_expenseName.setText(xpn.get_name());
					txt_expenseAmount.setText(xpn.get_amount()+"");
					cb_expenseCategory.setSelectedItem(_catManager.get(xpn.get_category()));
					cb_expenseByMem.setSelectedItem(_memManager.get(xpn.get_byMem().get_id()));
					cb_expensePaymentMethod.setSelectedItem(_payManager.get(xpn.get_paymentMethod().get_id()));
					txt_expensePaidTo.setText(xpn.get_partyInvolved());
					txt_expenseDescr.setText(xpn.get_comments());
					((JTextField)calendarDate.getDateEditor().getUiComponent()).setText(xpn.get_date().toString());
					cb_expenseFrequency.setSelectedItem(xpn.get_frequency());
					btn_saveEdit.setVisible(true);
					btn_cancelEdit.setVisible(true);
					if(isPeriod(xpn.get_frequency()))
					{
						btnStopUpdate.setVisible(true);
					}
					else
					{
						btnStopUpdate.setVisible(false);
					}

				}
				else
				{
					print("Please select an existing expense to edit.\n");
				}
			}

		});
		
		btn_saveEdit.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				int selectedRow = expenseTable.getSelectedRow();
				if(selectedRow>=0)
				{
					int editId = _search.getExpenseIdList().get(selectedRow);
					if(!validateInput())
						return;
					String cmd = CommandGenerator.getEditExpenseCmd(
							editId,
							txt_expenseName.getText(), 
							Double.parseDouble(txt_expenseAmount.getText()), 
							((Category)cb_expenseCategory.getSelectedItem()).get_id(), 
							((PaymentMethod)cb_expensePaymentMethod.getSelectedItem()).get_id(), 
							((FamilyMember)cb_expenseByMem.getSelectedItem()).get_id(), 
							txt_expensePaidTo.getText(), 
							cb_expenseFrequency.getSelectedItem().toString(),
							((JTextField)calendarDate.getDateEditor().getUiComponent()).getText(), 
							txt_expenseDescr.getText());
					_shell.readCmd(cmd);
					updateTable();
					btn_saveEdit.setVisible(false);
					btn_cancelEdit.setVisible(false);
					btnStopUpdate.setVisible(false);
					setDefault();
				}
				else
				{
					print("Please select an existing expense to delete.\n");
				}
			}
			
		});

		btn_cancelEdit.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				setDefault();
				btn_saveEdit.setVisible(false);
				btn_cancelEdit.setVisible(false);
				btnStopUpdate.setVisible(false);
			}
			
		});
		
		this.setDefault();
		this.updateAll();
	
	}
	
	//need to add _search set
	
	/**
	 * 
	 * @Precondition 
	 * @Postcondition 
	 */
	public void setDefault()
	{		
		txt_expenseName.setText("");
		txt_expenseAmount.setText("");
		cb_expenseCategory.setSelectedItem(_catManager.get(Expense.DEFAULT_CATEGORY));
		cb_expenseByMem.setSelectedItem(_memManager.get(0));
		cb_expensePaymentMethod.setSelectedItem(_payManager.get(0));
		txt_expensePaidTo.setText(Expense.DEFAULT_PARTYINVOLVED);
		txt_expenseDescr.setText(Expense.DEFAULT_COMMENTS);
		((JTextField)calendarDate.getDateEditor().getUiComponent()).setText("");
		cb_expenseFrequency.removeItem(Frequency.STOPPED);
		cb_expenseFrequency.setSelectedItem(Expense.DEFAULT_FREQUENCY);
		btn_saveEdit.setVisible(false);
		btn_cancelEdit.setVisible(false);
	}

	/**
	 * 
	 * @Precondition 
	 * @Postcondition 
	 */
	public void updateTable()
	{
		expenseRowData = _search.toExpenseVector();
		UneditableTable vectorTable = new UneditableTable(expenseRowData, Search.getToExpenseVectorColName());
		expenseTable = new JTable(vectorTable);
		expenseTable.addMouseListener(new MouseAdapter() {
			   public void mousePressed(MouseEvent e) {
			      if (e.getClickCount() > 1) {
			         JTable target = (JTable)e.getSource();
			         int row = target.getSelectedRow();
			         int column = target.getSelectedColumn();
			         expenseTable.removeEditor();
			         // do some action
			         btn_editExpense.doClick();		
			         }
			   }
			});
		expenseTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		for(int i=0;i<expenseTable.getColumnCount();i++)
		{
			expenseTable.getColumnModel().getColumn(i).setMinWidth(120);
		}
		
		scrollPane_xpnList.setViewportView(expenseTable);
		expenseTable.setRowSelectionAllowed(true);
		_sidePane.update();
		_tabPanelMgr.updateExpense();
	}
	
	private boolean isPeriod(Frequency get_frequency) {
		// TODO Auto-generated method stub
		boolean index=false;
		switch(get_frequency)
		{
		    case DAILY:   
		    case WEEKLY:
		    case MONTHLY:
		    case YEARLY:  index = true;
		}
		return index;
	}
	/**
	 * 
	 * @Precondition 
	 * @Postcondition 
	 */
	public void updateMember()
	{
		cbm_expenseMember = new DefaultComboBoxModel<FamilyMember>();
		for(FamilyMember mem: _memManager.getList())
		{
			cbm_expenseMember.addElement(mem);
		}
		cb_expenseByMem.setModel(cbm_expenseMember);
		
	}
	
	/**
	 * 
	 * @Precondition 
	 * @Postcondition 
	 */
	public void updateCategory()
	{
		cbm_expenseCategory = new DefaultComboBoxModel<Category>();
		for(Category cat: _catManager.getList())
		{
			cbm_expenseCategory.addElement(cat);
		}
		cb_expenseCategory.setModel(cbm_expenseCategory);
	}
	/**
	 * 
	 * @Precondition 
	 * @Postcondition 
	 */
	public void updatePayMethod()
	{
		cbm_expensePayMethod = new DefaultComboBoxModel<PaymentMethod>();
		for(PaymentMethod pm: _payManager.getList())
		{
			cbm_expensePayMethod.addElement(pm);
		}
		cb_expensePaymentMethod.setModel(cbm_expensePayMethod);
	}
	
	/**
	 * 
	 * @Precondition 
	 * @Postcondition 
	 */
	public void updateAll()
	{
		updateMember();
		updateCategory();
		updatePayMethod();
		updateTable();
	}
	
	public boolean validateInput()
	{
		if(!ValidateInput.validName(txt_expenseName.getText()))
		{
			return false;
		}
		if(!ValidateInput.validAmount(txt_expenseAmount.getText()))
		{
			return false;
		}
		if(!ValidateInput.validPartyInvolved(txt_expensePaidTo.getText(),"PaidTo"))
		{
			return false;
		}
		if(!ValidateInput.validDescription(txt_expenseDescr.getText(),"Description"))
		{
			return false;
		}
		if(!ValidateInput.validDate(calendarDate, "Date")) {
			return false;
		}
		
		//check date
		return true;
	}
	
	public Vector<Integer> getExpenseIDList() {
		return _search.getExpenseIdList();
	}
	
	
	public void print(String msg)
	{
		_sidePane.appendRecent(msg);
	}

	@Override
	public void updateExpense() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void updateIncome() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void updateLoan() {
		// TODO Auto-generated method stub
		
	}
	
}